package com.xiaolin.hrsystem.service.impl;

import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.xiaolin.hrsystem.model.dto.LogoutDto;
import com.xiaolin.hrsystem.model.dto.UserInfoFetch;
import com.xiaolin.hrsystem.model.entity.User;
import cn.hutool.json.JSONObject;
import com.xiaolin.hrsystem.service.SSOService;
import com.xiaolin.hrsystem.service.UserService;
import com.xiaolin.hrsystem.utils.ContextUtil;
import com.xiaolin.hrsystem.utils.OptResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author xiaolin
 * @description 描述
 * @since 2024/10/9
 */
@Service
public class SSOServiceImpl implements SSOService {
    @Autowired
    private UserService userService;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Value("${sso.auth.appKey}")
    private String appKey;

    @Value("${sso.auth.appSecret}")
    private String appSecret;

    private final String ssoInfoUrl = "http://127.0.0.1:12000/sso/ssoAuth/info";

    private final String ssoLogoutUrl = "http://127.0.0.1:12000/sso/ssoAuth/logout";

    private final String loginToken = "hr-token";

    public static void main(String[] args) {
        System.out.println(UUID.randomUUID().toString().replace("-", ""));
        System.out.println(UUID.randomUUID().toString().replace("-", ""));
    }

    @Override
    public OptResult login(String code, HttpServletResponse response) {
        // 1.校验是否有ticket，如果没有，返回错误码
        if (StringUtils.isEmpty(code)) {
            return new OptResult(400, null);
        }
        // 2.根据ticket从认证中心获取用户信息
        String authToken = UUID.randomUUID().toString();
        HttpRequest post = HttpUtil.createPost(ssoInfoUrl);
        UserInfoFetch userInfoFetch = new UserInfoFetch();
        userInfoFetch.setSystemFlag("http://127.0.0.1:12010/hr/userSsoAth/logoutCallback/");
        userInfoFetch.setToken(authToken);
        userInfoFetch.setCode(code);
        String paramStr = JSONUtil.toJsonStr(userInfoFetch);
        // 1、将请求参数与appSecret使用签名算法加密处理
        String sign = DigestUtil.sha256Hex(paramStr + appSecret);
        // 2、设置请求头（appKey、签名、时间戳、随机值）
        Map<String, List<String>> headers = new HashMap<>();
        headers.put("appKey", Collections.singletonList(appKey));
        headers.put("sign", Collections.singletonList(sign));
        headers.put("timestamp", Collections.singletonList(String.valueOf(new Date().getTime())));
        headers.put("nonce", Collections.singletonList(UUID.randomUUID().toString()));
        post.header(headers);
        // 3、设置请求参数
        post.body(paramStr);
        HttpResponse execute = post.execute();
        OptResult result = JSONUtil.toBean(execute.body(), OptResult.class);
        if (result.getCode() != 200) {
            return new OptResult(400, null);
        }
        // 3.校验用户id是否正确，校验失败则返回错误码
        JSONObject user = (JSONObject) result.getData().get("userInfo");
        User systemUser = userService.getById(user.getInt("id"));
        if (Objects.isNull(systemUser)) {
            return new OptResult(400, null);
        }
        // 4.保存用户信息到Redis
        redisTemplate.opsForValue().set(authToken, systemUser, 30, TimeUnit.MINUTES);
        // 5.给前端派发一个cookie
        Cookie cookie = new Cookie(loginToken, authToken);
        // 设置域名
        cookie.setDomain("hr.xl.com");
        // 设置路径
        cookie.setPath("/");
        // 设置超时时间
        long seconds = TimeUnit.MINUTES.toSeconds(60 * 24);
        cookie.setMaxAge((int) seconds);
        response.addCookie(cookie);
        return new OptResult(200, null);
    }

    @Override
    public OptResult info(HttpServletRequest request) {
        String token = ContextUtil.getToken(request, loginToken);
        if (StringUtils.isEmpty(token)) {
            return new OptResult(400, null);
        }
        User user = (User) redisTemplate.opsForValue().get(token);
        if (Objects.isNull(user)) {
            return new OptResult(400, null);
        }
        Map<String, Object> data = new HashMap<>();
        data.put("avatar", "https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif");
        data.put("introduction", "I am a super administrator");
        data.put("name", user.getName());
        data.put("roles", Collections.singletonList("admin"));
        return new OptResult(200, data);
    }

    @Override
    public OptResult logout(HttpServletRequest request) {
        // 1.调用认证中心接口进行注销
        String token = ContextUtil.getToken(request, loginToken);
        if (StringUtils.isEmpty(token)) {
            return new OptResult(400, null);
        }
        User user = (User) redisTemplate.opsForValue().get(token);
        if (Objects.isNull(user)) {
            return new OptResult(400, null);
        }

        HttpRequest post = HttpUtil.createPost(ssoLogoutUrl);
        LogoutDto logoutDto = new LogoutDto();
        logoutDto.setUserAccount(user.getUserAccount());
        post.body(JSONUtil.toJsonStr(logoutDto));
        HttpResponse execute = post.execute();
        System.out.println(execute);
        // 2.以防万一，再次删除用户的会话信息
        redisTemplate.delete(token);
        return new OptResult(200, null);
    }

    @Override
    public OptResult logoutCallback(String token) {
        // 1.校验用户是否过期，如果用户未过期则删除用户会话信息
        User user = (User) redisTemplate.opsForValue().get(token);
        if (Objects.nonNull(user)) {
            //
            redisTemplate.delete(token);
        }
        return new OptResult(200, null);
    }
}
